import { pushTarget, popTarget } from './dep.js';
import { queueWatcher } from './schedular.js';
let id = 0;
class Watcher {
    constructor(vm, exprOrFn, cb, options) {
        this.vm = vm;
        this.cb = cb;
        this.options = options;
        this.id = id++;
        this.user = options.user;//用来判断是否为用户watcher的状态
        this.sync = options.sync;//同步更新,不合并更新,
        this.lazy = options.lazy;//用来判断是否为计算属性watcher的状态
        this.dirty = options.dirty;//用来判断计算属性是否缓存状态
        //调用传入的函数,调用render方法,此时会对模板中的数据进行取值
        this.value = this.lazy ? undefined : this.get();
        if (typeof exprOrFn === 'function') {
            //将内部传递的表达式,挂载在getter属性上
            this.getter = exprOrFn;
        } else {
            //封装getter为取值函数
            this.getter = function () {
                //如果监听的值为a.b.c.d,以.分割成数组[a,b,c,d]
                let path = exprOrFn.split('.');
                //获取当前实例
                let val = vm;
                //[a,b,c,d]
                for (let i = 0; i < path.length; i++) {
                    //val=vm.a => vm.a=vm.a.b => vm.a.b=vm.a.b,c => vm.a.b.c = vm.a.b.c.d
                    val = val[path[i]];
                }
                //最终拿到vm.a.b.c.d
                return val;
            }
        }

        //用来记录dep
        this.deps = [];
        //dep的唯一标识
        this.depsId = new Set();

    }
    get() {
        //存储当前这个watcher
        //debugger
        pushTarget(this);
        //会对属性进行取值操作
        let value = this.getter.call(this.vm);
        //删除当前这个watcher
        popTarget();
        return value;
    }
    //watcher记住dep
    addDep(dep) {
        //dep的唯一标识
        let id = dep.id;
        //去重dep,dep非重复,watcher也是不重复的
        //debugger;
        if (!this.depsId.has(id)) {
            this.depsId.add(id);
            this.deps.push(dep);
            //dep记住当前watcher
            dep.addSub(this);
        }
    }
    //执行渲染逻辑
    run() {
        let oldValue = this.value;//第一次渲染的值
        let newValue = this.get();
        this.value = newValue;
        //用户watcher,就执行用户定义的callback
        if (this.value) {
            this.cb.call(this.vm, newValue, oldValue)
        }
    }
    //更新视图(防抖,批量更新)
    update() {
        //this.get()
        //console.log(this)
        if (this.sync) {
            this.run()
        }else if (this.lazy){//计算属性更改值需要更新
            this.dirty=true
        }else {
            //调用watcher队列函数,合并更新,去掉同名更新
            queueWatcher(this)
        }

    }
    //计算属性watcher用户取值方法
    evalute() {
        this.value = this.get();
        this.lazy = false;
    }
    //计算属性watcher同时收集渲染watcher达到视图一并更新
    depend() {
        let i = this.deps.length;
        while (i--) {
            this.deps[i].depend();
        }
    }

    //当属性取值时,记住这个watcher,稍后数据变化,去执行自己记住的wather即可

}

export default Watcher;